﻿using HuiLian.Common.Attributes;
using HuiLian.Common.Configs;
using SkiaSharp;
using System;
using System.Text;

namespace HuiLian.Common.Helpers
{
    [SingleInstance]
    public class VerifyCodeHelper
    {
        private readonly AppConfig _appConfig;

        public VerifyCodeHelper(AppConfig appConfig)
        {
            _appConfig = appConfig;
        }

        private static string GenerateRandom(int length)
        {
            var chars = new StringBuilder();
            //验证码的字符集，去掉了一些容易混淆的字符
            char[] character = { '2', '3', '4', '5', '6', '8', '9', 'a', 'b', 'd', 'e', 'f', 'h', 'k', 'm', 'n', 'r', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' };
            Random rnd = new();
            //生成验证码字符串
            for (int i = 0; i < length; i++)
            {
                chars.Append(character[rnd.Next(character.Length)]);
            }
            return chars.ToString();
        }

        public byte[] Draw(out string code, int length = 4)
        {
            int fontSize = 22;
            int spaceBetween = 2;
            Random random = new();

            byte[] fileBytes = Array.Empty<byte>();
            code = GenerateRandom(length);

            //字体列表，用于验证码
            string[] fonts = _appConfig.VarifyCode.Fonts;

            if (!string.IsNullOrWhiteSpace(code))
            {
                int num = (fontSize + spaceBetween) * length + 5;
                int num2 = fontSize + 11;
                using SKBitmap skbitmap = new(num, num2, false);
                using SKCanvas skcanvas = new(skbitmap);
                skcanvas.Clear();
                skcanvas.DrawColor(new SKColor(0, 0, 0, 0));
                using (SKPaint skpaint = new())
                {
                    if (fonts.Length > 0)
                    {
                        skpaint.Typeface = SKTypeface.FromFamilyName(fonts[random.Next(fonts.Length)]);
                    }
                    for (int i = 0; i < length; i++)
                    {
                        skpaint.Color = new SKColor((byte)random.Next(0, 255), (byte)random.Next(0, 255), (byte)random.Next(0, 255));
                        skpaint.TextSize = fontSize;
                        skcanvas.DrawText(code[i].ToString(), i * fontSize + spaceBetween, fontSize, skpaint);
                    }

                    int num3 = num / 2;
                    for (int j = 0; j < 2; j++)
                    {
                        skpaint.Color = new SKColor((byte)random.Next(0, 255), (byte)random.Next(0, 255), (byte)random.Next(0, 255));
                        skcanvas.DrawLine(random.Next(0, num3), random.Next(1, num2), random.Next(num3 + 1, num), random.Next(1, num2), skpaint);
                    }
                }
                using SKImage skimage = SKImage.FromBitmap(skbitmap);
                using SKData skdata = skimage.Encode(SKEncodedImageFormat.Png, 100);
                fileBytes = skdata.ToArray();
            }
            return fileBytes;
        }

        public string GetBase64String(out string code, int length = 4)
        {
            return Convert.ToBase64String(Draw(out code, length));
        }
    }
}